﻿#region Copyright Statement
//  ------------------------------------------------------------------------------
//  
//    This file is part of The Streambolics Library.
//    Copyright © 2005-2009, Stephan Leclercq & Streambolics
//    All rights reserved.
//  
//    The Streambolics Library is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//  
//    The Streambolics Library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//  
//    You should have received a copy of the GNU General Public License
//    along with Streambolics; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//  
//  ------------------------------------------------------------------------------
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Streambolics
{
    public static class ByteArrayExtensions
    {
        private static void AppendHex (StringBuilder aBuilder, byte[] aBlock, int aStart, int aEnd, int aMax)
        {
            for (int i = aStart; i < aEnd; i++)
            {
                aBuilder.AppendFormat ("{0:X2} ", aBlock[i]);
            }
            for (int i = aEnd; i < aMax; i++)
            {
                aBuilder.Append ("   ");
            }

            for (int i = aStart; i < aEnd; i++)
            {
                byte b = aBlock[i];
                if (b > 32 && b < 127)
                {
                    aBuilder.Append ((char)b);
                }
                else
                {
                    aBuilder.Append ('.');
                }
            }

            aBuilder.Append ("\r\n");
        }

        /// <summary>
        ///     A string representing the hexadecimal dump of the
        ///     bytes in the array.
        /// </summary>
        /// <param name="s">
        ///     The array to dump.
        /// </param>
        /// <param name="aLineLength">
        ///     The number of bytes on each text line.
        /// </param>
        /// <returns>
        ///     A string consisting of lines with the hexadecimal
        ///     dump.
        /// </returns>

        public static string HexDump (this byte[] s, int aLineLength)
        {
            int start = 0;
            int max = s.Length;
            StringBuilder sb = new StringBuilder ();

            while (start < max)
            {
                int end = start + aLineLength;
                if (end > max)
                {
                    end = max;
                }
                AppendHex (sb, s, start, end, start + aLineLength);
                start = end;
            }
            return sb.ToString ();
        }

        public static string HexDump (this byte[] s)
        {
            return HexDump (s, 16);
        }

        /// <summary>
        ///     A copy of the array with a new size.
        /// </summary>
        /// <param name="s">
        ///     The array to copy.
        /// </param>
        /// <param name="aNewSize">
        ///     The new size of the array.
        /// </param>
        /// <returns>
        ///     A copy of the array with the new size.
        /// </returns>
        /// <remarks><para>
        ///     The array is copied even if the new size is the
        ///     same as the current size.
        /// </para></remarks>

        public static byte[] Resize (this byte[] s, int aNewSize)
        {
            int l = s.Length;

            byte[] m = new byte[aNewSize];

            // TODO : use Buffer.BlockCopy instead
            System.Array.Copy (s, m, System.Math.Min (l, aNewSize));
            return m;
        }
    }
}
